import {
  computed,
  inject,
  ref,
  unref,
  watch,
  nextTick,
  type ExtractPropTypes,
  type InjectionKey,
  type MaybeRef,
  type PropType,
} from 'vue';

import { cloneDeep } from 'lodash-es';
import { type TableColumnConfig } from '../table-column/table-column';
import { STATES, type State } from '../libs/constant';
import {
  useDataSource,
  type DataSource,
  type DataSourceItem,
} from '../libs/data-source';

// 返回状态的助手函数
export type StateMethod = (state: any) => State;

export const props = {
  expandId: String,
  state: String as PropType<State>,
  dataSource: {
    type: Object as PropType<DataSource<unknown>>,
    default: () => useDataSource(),
  },
  data: {
    type: Array as PropType<MaybeRef<any[]>>,
    default: null,
  },
  border: Boolean,
  shadow: Boolean,
  stateField: {
    type: String,
    default: 'state',
  },
  stateMethod: {
    type: Function as PropType<StateMethod>,
    default: (state: any) => {
      if (Object.keys(STATES).includes(state)) {
        return STATES[state as State];
      }
      return 'view';
    },
  },
  // 添加一行的默认值
  defaultValue: {
    type: Object,
    default: () => ({}),
  },
  addMethod: {
    type: Function as PropType<Function | undefined>,
    default: undefined,
  },
};

export type ExtraTableProps = ExtractPropTypes<typeof props>;

export type ExtraTableEmits = {
  submit: [data: any[], parent?: object];
  remove: [row: object];
  update: [row: object];
  add: [row: object];
};

export const useTableContext = (
  props: ExtraTableProps,
  Emits: (...args: any) => any
) => {
  const { data, dataSource, stateField, stateMethod } = props;
  // if (data !== null) dataSource.value = unref(data);
  //TODO 状态转换先凑合用，回头给DataSource加上format方法
  if (data) {
    initData(unref(data));
  }

  watch(
    () => props.data,
    () => {
      initData(unref(props.data));
    }
  );

  function initData(data: any[]) {
    const state = props.state;
    const newData = cloneDeep(data).map((e) => {
      (e as DataSourceItem).__state__ =
        // 如果有父组件easy-tablec当前行的状态，则状态为easy-table的状态
        // 否则为自身状态
        state ?? stateMethod(e[stateField]);
      return e;
    });
    dataSource.value = newData;
  }

  const setData = (value: any[]) => initData(unref(value));
  const getData = () => dataSource.raw();

  const columns = ref<TableColumnConfig[]>([]);

  const states = computed(() =>
    dataSource.value.map((e) => e.__state__)
  );

  // let easyTableColumn;
  // nextTick(() => {
  //   easyTableColumn = inject(easyTableColumnKey, undefined);
  //   console.log('🚀 ~ easyTableColumn:', easyTableColumn);
  // });

  const setStates = (index: number, state: State) => {
    dataSource.update({ __state__: state }, index);
  };

  // 过滤非extra的table-column
  const filterColumnsWidth = (columnConfigs: TableColumnConfig[]) => {
    return columnConfigs
      .filter((cfg) => !cfg.extra)
      .map((cfg) => cfg.width);
  };

  // 统一table-column的width为String，如：'100px 1fr 1fr'
  const formatGirdColumns = (widths: (number | string)[]) => {
    const gridColumns = widths.map((w) => {
      if (typeof w === 'number') return w + 'px';
      return w;
    });
    return gridColumns.join(' ');
  };

  const gridTemplateColumnsStyle = computed(() => {
    const columnWidths = filterColumnsWidth(columns.value);
    return formatGirdColumns(columnWidths);
  });

  // 增加、删除、复制
  const add = async (item?: any, index?: number) => {
    let newItem = props.defaultValue;
    if (typeof item === 'object') {
      newItem = item;
    } else if (props.addMethod) {
      newItem = await props.addMethod();
    }

    dataSource.insert(newItem, index);
  };
  const del = (index: number) => {
    dataSource.remove(index);
  };
  const copy = (index: number) => {
    dataSource.copy(index);
  };

  const edit = (index: number) => {
    setStates(index, 'edit');
  };
  const save = (index: number) => {
    setStates(index, 'view');
  };

  return {
    dataSource: props.dataSource,
    setData,
    getData,

    add,
    del,
    copy,
    edit,
    save,

    columns,
    registryColumns: (column: TableColumnConfig) => {
      columns.value.push(column);
    },

    states,
    setStates,

    gridTemplateColumnsStyle,
  };
};

export type TableContext = ReturnType<typeof useTableContext>;

export const tableContextInjectKey: InjectionKey<TableContext> =
  Symbol('extra-table');
